/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) 2024 Intel Corporation
 */

#ifndef SPDK_INTERNAL_NVME_H
#define SPDK_INTERNAL_NVME_H

#include "spdk/keyring.h"
#include "spdk/nvme.h"
#include "spdk/nvmf_spec.h"
#include "spdk/stdinc.h"

/**
 * Calculate a response to a DH-HMAC-CHAP challenge.
 *
 * \param key DH-HMAC-CHAP key.
 * \param hash Hash function to use.
 * \param type Challenge type ("HostHost" for host challenge or "Controller" for controller
 * challenge).
 * \param seq Sequence number.
 * \param tid Transaction ID.
 * \param scc Secure channel concatenation.
 * \param nqn1 Host/Subsystem NQN, depending on challenge type (hostnqn for host challenge,
 * subnqn for controller challenge).
 * \param nqn2 The other NQN (if nqn1==hostnqn, then nqn2==subnqn).
 * \param dhkey Diffie-Hellman secret.
 * \param dhlen Size of `dhkey`.
 * \param cval Challenge value.  Its size must be large enough to keep a digest generated by `hash`
 * function (e.g. at least 32B for sha256, 48B for sha384, etc.).
 * \param rval Response buffer.  Its size must be large enough to keep a digest generated by `hash`
 * function (e.g. at least 32B for sha256, 48B for sha384, etc.).
 *
 * \return 0 on success, negative errno otherwise.
 */
int spdk_nvme_dhchap_calculate(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
			       const char *type, uint32_t seq, uint16_t tid, uint8_t scc,
			       const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
			       const void *cval, void *rval);

/** DH-HMAC-CHAP Diffie-Hellman key */
struct spdk_nvme_dhchap_dhkey;

/**
 * Generate a Diffie-Hellman key.
 *
 * \param dhg Diffie-Hellman group.
 *
 * \return Diffie-Hellman key or NULL on failure.
 */
struct spdk_nvme_dhchap_dhkey *spdk_nvme_dhchap_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhg);

/**
 * Free a DH key generated with `spdk_nvme_dhchap_generate_dhkey()`.
 *
 * \param key DH key.  If NULL, this function is a no-op.
 */
void spdk_nvme_dhchap_dhkey_free(struct spdk_nvme_dhchap_dhkey **key);

/**
 * Get the public part of a DH key.
 *
 * \param key DH key.
 * \param pub Buffer to hold the public key.
 * \param len Length of the `pub` buffer.  After a successful call to this function, this variable
 * will hold the length of the public key.
 *
 * \return 0 on success or negative errno on failure.
 */
int spdk_nvme_dhchap_dhkey_get_pubkey(struct spdk_nvme_dhchap_dhkey *key, void *pub, size_t *len);

/**
 * Derive a secret from a DH key and peer's public key.
 *
 * \param key DH key.
 * \param peer Peer's public key.
 * \param peerlen Length of the peer's public key.
 * \param secret Buffer to hold the secret value.
 * \param seclen Length of the `secret` buffer.  After a successful call to this function, this
 * variable will hold the length of the secret value.
 *
 * \return 0 on success or negative errno on failure.
 */
int spdk_nvme_dhchap_dhkey_derive_secret(struct spdk_nvme_dhchap_dhkey *key, const void *peer,
		size_t peerlen, void *secret, size_t *seclen);

#endif /* SPDK_INTERNAL_NVME_H */
